package org.bsscheduler;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author tblackstone
 */
public class Calendar {

    private EventList events;

    public Calendar() {
    }

    public void setEventList(EventList events) {
        this.events = events;
    }

    public EventList getEventList() {
        return events;
    }

    /**
     * Create a default calendar starting with the current month and extending
     * out for the current month.
     * @return the HTML String generated
     */
    public String createCalendar() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        GregorianCalendar month = new GregorianCalendar();
        month.set(GregorianCalendar.DATE, 1);
        System.out.println("--Calendar default");
        return (createCalendar(sdf.format(month.getTime())));
    }

        /**
     * Creates a new HTML calendar starting with the given week, and extending
     * out for 6 weeks.
     * @param startDate a date in the first week to display, in the form
     * 'yyyy-MM-dd'
     * @return the HTML String generated
     */
    public String createCalendar(String startDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        GregorianCalendar month = new GregorianCalendar();
        try {
            month.setTime(sdf.parse(startDate));
        } catch (ParseException ex) {
            // Ignore parse error, it will default to first day of current month
        }
        //int dayOfWeek = month.get(GregorianCalendar.DAY_OF_WEEK);
        //int daysInMonth = month.getActualMaximum(GregorianCalendar.DATE);
        //int weeks = (int)Math.ceil((dayOfWeek + daysInMonth  - 1.0f) / 7.0f);
        return (createCalendar(sdf.format(month.getTime()), 6));
    }

    /**
     * Creates a new HTML calendar starting with the current week, and extending
     * out for the specified number of weeks. The valid range for numWeeks is
     * between 1 and 10, inclusive.
     * @param numWeeks the number of weeks to include in the calendar
     * @return the HTML String generated
     */
    public String createCalendar(int numWeeks) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        GregorianCalendar month = new GregorianCalendar();
        return (createCalendar(sdf.format(month), numWeeks));
    }

    /**
     * Creates a new HTML calendar starting with the given week, and extending
     * out for the specified number of weeks. The valid range for numWeeks is
     * between 1 and 10, inclusive.
     * @param startDate a date in the first week to display, in the form
     * 'yyyy-MM-dd'
     * @param numWeeks the number of weeks to include in the calendar
     * @return the HTML String generated
     */
    public String createCalendar(String startDate, int numWeeks) {

        String output = "";

        TreeMap<String, String> userList = UsersDB.userList();

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            GregorianCalendar firstDay = new GregorianCalendar();
            firstDay.setFirstDayOfWeek(GregorianCalendar.SUNDAY);
            firstDay.setTime(sdf.parse(startDate));
            GregorianCalendar currentDay = (GregorianCalendar) firstDay.clone();

            int dayOfWeek = currentDay.get(GregorianCalendar.DAY_OF_WEEK);
            currentDay.add(GregorianCalendar.DATE, 1 - dayOfWeek);

            String[] months = {"Jan", "Feb",
                "Mar", "Apr", "May", "Jun", "Jul",
                "Aug", "Sep", "Oct", "Nov",
                "Dec"};


            if (numWeeks < 1 || numWeeks > 10) {
                numWeeks = 5;
            }

            output += "<table width=\"100%\" id=\"calendar\">\n";
            output += "<tr class=\"cal_header\">\n" +
                    "<td>Sun</td>" +
                    "<td>Mon</td>" +
                    "<td>Tue</td>" +
                    "<td>Wed</td>" +
                    "<td>Thu</td>" +
                    "<td>Fri</td>" +
                    "<td>Sat</td>" +
                    "</tr>\n";

            // Create calendar
            for (int i = 0; i < numWeeks; i++) {
                output += "<tr>\n";
                for (int d = 0; d < 7; d++) {

                    String day = Integer.toString(currentDay.get(GregorianCalendar.DATE));

                    // Is the date in the current month
                    // if not, use different class
                    String monthClass = "";
                    if (currentDay.get(GregorianCalendar.MONTH) !=
                            firstDay.get(GregorianCalendar.MONTH)) {
                        monthClass = "not_month";
                    } else {
                        monthClass = "month";
                    }


                    //find out if there's any appointments that day
                    // if so add appropriate tags
                    String dateString = sdf.format(currentDay.getTime());
                    SortedSet<Event> currentDayEventList = events.getEventsForDate(dateString);

                    // Only handle click event if there are no events for today
                    String clickEvent = "";
                    if (currentDayEventList.size() == 0) {
                        monthClass += "_no_events";
                        clickEvent = " onclick=\"javascript:showCreateDialog('" +
                            dateString + "')\"";
                    }

                    output += "<td class=\"" + monthClass + "\"" + clickEvent + ">";

                    output += "<p>";

                    if (currentDayEventList.size() > 0) {
                        output += "<span class=\"createevent_link\" onclick=\"javascript:showCreateDialog('" +
                            dateString + "')\">add</span>\n";
                    } else {
                        output += "<span class=\"no_events\">\n";
                    }

                    // if it is the first month on the calendar
                    // add month name to date
                    if(i==0 && d==0){
                        output += months[currentDay.get(GregorianCalendar.MONTH)] + " ";
                    } else if (currentDay.get(GregorianCalendar.DAY_OF_MONTH) == 1) {
                        // if it is the beginning of the month, add
                        // month name to date
                        output += months[currentDay.get(GregorianCalendar.MONTH)] + " ";
                    }

                    output += day;

                    output += "</p>\n";
                    
                    int numEvents = 0;
                    boolean outputMoreEventsLink = false;
                    for (Event e : currentDayEventList) {

                        // Do not show events that have been declined
                        if (e.getParticipantStatus(events.getUsername()).equals("declined")) {
                            continue;
                        }


                        String eventClass = "cal_event";
                        if (e.getParticipantStatus(events.getUsername()).equals("requested")) {
                            eventClass += "_requested";
                        }
                            
                        Vector<String> participants = new Vector<String>();
                        participants.add(e.getCreator());
                        participants.addAll(e.getParticipants());

                        String participantArray = "[";
                        for (String p: participants) {
                            String fullName = userList.get(p);
                            String status = e.getParticipantStatus(p);
                            participantArray += "[\\'" + fullName + "\\', \\'" +
                                    status + "\\'],";
                        }
                        // Remove last comma
                        participantArray = participantArray.substring(0,
                                participantArray.length() - 1);
                        participantArray += "]";
                                    
                        String eventString = "<div class=\"" + eventClass + "\" onclick=\"" +
                                "showModifyDialog('" +
                                e.getUUID() + "', '" +
                                e.getTitleEncoded() + "', '" +
                                e.getDescriptionEncoded() + "', '" +
                                e.getStartDate("yyyy-MM-dd") + "', '" +
                                e.getStartDate("H:mm") + "', '" +
                                e.getEndDate("yyyy-MM-dd") + "', '" +
                                e.getEndDate("H:mm") + "', '" +
                                participantArray + "')\")>";

                        eventString += e.getStartDate("h:mm a") + " - " +
                                e.getEndDate("h:mm a");

                        eventString += "</div>\n";

                        // Only show up to 3 events each day
                        if (numEvents < 3) {
                            output += eventString;
                            numEvents++;
                        } else {

                            // Show rest of events on a hover-div
                            if (outputMoreEventsLink == false) {
                                output += "<div class=\"more_events_link\">more...\n" +
                                        "<div class=\"more_events_box\">";
                                outputMoreEventsLink = true;
                            }
                            output += eventString;

                            numEvents++;
                        }

                    }

                    if (outputMoreEventsLink) {
                        output += "</div>\n</div>\n";
                    }
                    
                    if (currentDayEventList.size() == 0) {
                        output += "</span>\n";
                    }

                    output += "</td>\n";

                    // Increment date to next day
                    currentDay.add(GregorianCalendar.DATE, 1);
                }

                output += "  </tr>\n";
            }

            output += "</table>\n";

            
            output += "<script type=\"text/javascript\">\n" +
                      "    // show more events popup when hovering on 'more'\n" +
                      "    $(\".more_events_link\").hover(\n" +
                      "        function () {\n" +
                      "            $(this).find(\".more_events_box\").show(\"normal\");\n" +
                      "            return false;\n" +
                      "        } ," +
                      "        function () {\n" +
                      "            $(this).find(\".more_events_box\").hide(\"normal\");\n" +
                      "            return false;\n" +
                      "        });" +
                       "</script>";

        } catch (ParseException ex) {
            Logger.getLogger(Calendar.class.getName()).log(Level.SEVERE, null, ex);
        }


        return output;
    }


    public static int getCurrentMonth(){
        DateFormat dateFormat = new SimpleDateFormat("MM");
        Date date = new Date();
        return Integer.parseInt(dateFormat.format(date));
    }

    public static int getCurrentYear(){
        DateFormat dateFormat = new SimpleDateFormat("yyyy");
        Date date = new Date();
        return Integer.parseInt(dateFormat.format(date));
    }

    public static String getMonth(int month){
          String[] months = {"January", "February",
                "March", "April", "May", "June", "July",
                "August", "September", "October", "November",
                "December"};

          return months[ (month-1) ];

    }


}




